package com.googlecode.entity_dao.core.criteria;

import org.apache.commons.lang.ObjectUtils;

/**
 * Association path element contained in the {@link AssociationPath}.
 * 
 * <p>
 * 
 * Each element has a <tt>value</tt> corresponding with the given persistent entity property name. An optional
 * <tt>joinType</tt> is used to specify the type of join to use when creating related subcriteria within the
 * {@link AssociationPathRegister}.
 * 
 * <p>
 * 
 * This class is immutable by design so you can safely reuse its instances across the code.
 * 
 * @see AssociationPath
 * @see AssociationPathRegister
 * 
 * @author michal.jemala
 * @author vojtech.szocs
 * @author mauro.franceschini
 */
public class AssociationPathElement {

    private final String value;
    private final NestedPropertyJoinType joinType;

    /**
     * Creates a new association path element.
     * 
     * @param value Persistent entity property name.
     * @param joinType Type of join to use when creating related subcriteria.
     */
    public AssociationPathElement(String value, NestedPropertyJoinType joinType) {
        this.value = value;
        this.joinType = joinType;
    }

    /**
     * Creates a new association path element using the default join type.
     * 
     * @param value Persistent entity property name.
     */
    public AssociationPathElement(String value) {
        this(value, NestedPropertyJoinType.DEFAULT);
    }

    /**
     * @return Persistent entity property name.
     */
    public String getValue() {
        return value;
    }

    /**
     * @return Type of join to use when creating related subcriteria.
     */
    public NestedPropertyJoinType getJoinType() {
        return joinType;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;

        result = prime * result + ObjectUtils.hashCode(joinType);
        result = prime * result + ObjectUtils.hashCode(value);

        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;

        AssociationPathElement other = (AssociationPathElement) obj;

        return ObjectUtils.equals(joinType, other.joinType) && ObjectUtils.equals(value, other.value);
    }

    @Override
    public String toString() {
        return new StringBuilder(value).append(" [").append(joinType.toString()).append("]").toString();
    }
}
